package czh.cocoa.foundation;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class NSNotificationCenter extends NSObject {

	private static NSNotificationCenter sInstance;
	
	private NSMutableArray mNotificationItems;
	
	public static NSNotificationCenter defaultCenter() {
		if (sInstance == null) {
			sInstance = new NSNotificationCenter();
		}
		return sInstance;
	}
	
	private NSNotificationCenter() {
		mNotificationItems = new NSMutableArray();
	}
	
	public void addObserverSelectorNameObject(NSObject observer, NSString selector, 
			     NSString name, NSObject sender) {
		NotificationItem item = new NotificationItem();
		item.observer = observer;
		item.selector = selector;
		item.name = name;
		item.sender = sender;
		if (!mNotificationItems.containsObject(item)) {
			mNotificationItems.addObject(item);
		}
	}
	
	public void postNotification(NSNotification note) {
		for (NSObject o : mNotificationItems) {
			NotificationItem item = (NotificationItem) o;
			if (item.name.isEqual(note.name())) {  
				if (item.sender == null || item.sender == note.object()) { 
					Class<?> clazz = item.observer.getClass();
					String mname = item.selector.toString();
					try {
						Method method = clazz.getDeclaredMethod(mname, NSNotification.class);
						method.setAccessible(true);
						method.invoke(item.observer, note);
					} catch (NoSuchMethodException e) {
						throw new RuntimeException("observer can't response this selector: " + mname);
					} catch (Exception e) { 
						e.printStackTrace();
					} 
				}
			}
		}
	}
	
	public void postNotificationNameObject(NSString name, NSObject sender) {
		postNotificationNameObjectUserInfo(name, sender, null);
	}
	
	public void postNotificationNameObjectUserInfo(NSString name, NSObject sender, NSDictionary userInfo) {
		NSNotification note = new NSNotification(name, sender, userInfo);
		postNotification(note);
	}
	
	public void removeObserver(NSObject observer) {
		NSArray items = new NSArray(mNotificationItems);
		for (int i = 0; i < items.count(); i++) {
			NotificationItem item = (NotificationItem) items.objectAtIndex(i); 
			if (item.observer == observer) {  
				mNotificationItems.removeObjectAtIndex(i); 
			}
		}
	}
	
	public void removeObserverNameObject(NSObject observer, NSString name, NSObject sender) {
		NSArray items = new NSArray(mNotificationItems);
		for (int i = 0; i < items.count(); i++) {
			NotificationItem item = (NotificationItem) items.objectAtIndex(i); 
			if (item.observer == observer && item.name.isEqual(name)) {  
				if (item.sender == null || item.sender == sender) { 
					mNotificationItems.removeObjectAtIndex(i); 
				}
			}
		}
	}
	
	private class NotificationItem extends NSObject {
		
		public NSObject observer;
		
		public NSString selector;
		
		public NSString name;
		
		public NSObject sender;
		
		public boolean isEqual(NSObject o) {
			if (o instanceof NotificationItem) {
				NotificationItem other = (NotificationItem) o;
				return other.observer == observer && other.selector.isEqual(selector) && name.isEqual(name);
			}
			return false;
		}
		
	}
	
}
